# @Time : 2020/10/13 13:39 
# @Author : Michael
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt


class Config:
    def __init__(self):
        pass

    MIN_MATCH_COUNT = 8
    FLANN_INDEX_KDTREE = 0


class MatchTemplates:

    def __init__(self, image1, image2):
        """
        传入图片路径
        :param image1:
        :param image2:
        :return:
        """
        self.gray1 = self.image1 = cv.imread(image1)
        self.gray2 = self.image2 = cv.imread(image2)

    def Resize(self, which, dsize, fx, fy):
        if which == 1:
            self.gray1 = cv.resize(self.gray1, dsize=dsize, fx=fx, fy=fy)
        elif which == 2:
            self.gray2 = cv.resize(self.gray2, dsize=dsize, fx=fx, fy=fy)
        else:
            print("resize parameter error")

    def Gray(self):
        self.gray1 = cv.cvtColor(self.gray1, cv.COLOR_BGR2GRAY)
        self.gray2 = cv.cvtColor(self.gray2, cv.COLOR_BGR2GRAY)

    def SHomography(self):
        sift = cv.SIFT_create()
        kp1, des1 = sift.detectAndCompute(self.gray1, None)
        kp2, des2 = sift.detectAndCompute(self.gray2, None)

        # 定义FLANN匹配器
        index_params = dict(algorithm=Config.FLANN_INDEX_KDTREE, trees=5)
        search_params = dict(checks=50)
        flann = cv.FlannBasedMatcher(index_params, search_params)
        # 使用KNN算法匹配
        matches = flann.knnMatch(des1, des2, k=2)

        # 去除错误匹配
        good = []
        for m, n in matches:
            if m.distance < 0.7 * n.distance:
                good.append(m)

        # 单应性
        if len(good) > Config.MIN_MATCH_COUNT:
            # 改变数组的表现形式，不改变数据内容，数据内容是每个关键点的坐标位置
            src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
            dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

            # findHomography 函数是计算变换矩阵
            # 参数cv2.RANSAC是使用RANSAC算法寻找一个最佳单应性矩阵H，即返回值M
            # 返回值：M 为变换矩阵，mask是掩模
            M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
            h, w = self.gray1.shape[:2]

            # pts是图像img1的四个顶点
            pts = np.float32([[0, 0],
                              [0, h - 1],
                              [w - 1, h - 1],
                              [w - 1, 0]]).reshape(-1, 1, 2)
            # 计算变换后的四个顶点坐标位置
            dst = cv.perspectiveTransform(pts, M)
            # 根据四个顶点坐标位置在img2图像画出变换后的边框

            # 透视变换
            MM = cv.getPerspectiveTransform(dst, pts)
            warp = cv.warpPerspective(self.image2.copy(), MM, (w, h))
            cv.polylines(self.image2, [np.int32(dst)], True, (0, 0, 255), 2, cv.LINE_AA)

            return warp, self.image2
        else:
            print("Not enough matches are found - %d/%d" % (len(good), Config.MIN_MATCH_COUNT))
            exit(999)
            return None

    def draw_rect(self):

        return
